package com.huajx.ld.codec;

import java.nio.charset.Charset;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.AttributeKey;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.huajx.tcpserver.kit.MessageKit;

public class TbDecoderAdapter extends CumulativeProtocolDecoder {

	private static final Logger logger = LoggerFactory.getLogger(TbDecoderAdapter.class);
	// final byte[] key = { (byte) 0xb9, (byte) 0xda, 0x5e, 0x15, 0x46, 0x57,
	// (byte) 0xa7, (byte) 0x8d, (byte) 0x9d,
	// (byte) 0x84, (byte) 0x90, (byte) 0xd8, (byte) 0xab, 0x00, (byte) 0x8c,
	// (byte) 0xbc, (byte) 0xd3, 0x0a,
	// (byte) 0xf7, (byte) 0xe4, 0x58, 0x05, (byte) 0xb8, (byte) 0xb3, 0x45,
	// 0x06, (byte) 0xd0, 0x2c, 0x1e,
	// (byte) 0x8f, (byte) 0xca, 0x3f };

	private final Charset codePage;
	private final boolean isServer;
	private final boolean isPassiveEncryption;

	// 包头8 (同步帧3 + 序号4 + 版本号1) + 机器号18 + 包内容长度 4 + 功能号 2
	private static final int PACK_HEADER = 32;

	public TbDecoderAdapter(Charset charset, boolean isServer, boolean isPassiveEncryption) {
		this.codePage = charset;
		this.isServer = isServer;
		this.isPassiveEncryption = isPassiveEncryption;
	}

	@Override
	protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
		int len = in.remaining();
		if (len >= PACK_HEADER) {
			// 一个可以记忆的Position位置的值，在调用reset()方法时会将缓冲区的Position重置为该索引，并非总是需要定义Mark，
			// 但是在定义Mark时，不能将其定义为负数，并且不能让它大于Position，
			// 如果定义了Mark，则在该Position或Limit调整为小于该Mark值时，该Mark将被丢弃。
			in.mark();

			byte[] bytes = new byte[PACK_HEADER];

			// get操作会导致下面的remaining()值发生变化, 这里减去了相应的长度
			in.get(bytes);

			int packLen = MessageKit.getInt(bytes, 26, 4);

			if (in.remaining() < packLen) {
				// 如果消息内容不够，则重置恢复position位置到操作前,进入下一轮, 接收新数据，以拼凑成完整数据
				in.reset();
				return false;
			} else {
				// 消息内容足够
				// 重置恢复position位置到操作前
				in.reset();

				// 取出完整包
				byte[] packArr = new byte[PACK_HEADER + packLen];
				in.get(packArr);

				// 输出字符串
				out.write(packArr);

				if (in.hasRemaining()) {
					return true;
				}

				return false;
			}
		}

		// if ( len > 4) {// 前4字节是包头
		// // 标记当前position的快照标记mark，以便后继的reset操作能恢复position位置
		// in.mark();
		// byte[] bytes = new byte[len];
		// in.get(bytes);
		//
		// out.write(bytes);
		// if (in.remaining() > 0) {// 如果读取一个完整包内容后还粘了包，就让父类再调用一次，进行下一次解析
		// return true;
		// }
		// }
		// logger.info("IoBuffer长度:{}", len);
		return false;// 处理成功，让父类进行接收下个包
	}

	public static String ioBufferToString(IoBuffer iobuffer) {
		iobuffer.flip(); // 调换buffer当前位置，并将当前位置设置成0
		byte[] b = new byte[iobuffer.limit()];
		iobuffer.get(b);
		// 此处用stringbuffer是因为
		// String类是字符串常量，是不可更改的常量。而StringBuffer是字符串变量，它的对象是可以扩充和修改的。
		StringBuffer stringBuffer = new StringBuffer();

		for (int i = 0; i < b.length; i++) {
			stringBuffer.append((char) b[i]); // 可以根据需要自己改变类型
		}
		logger.info(stringBuffer.toString());
		return stringBuffer.toString();
	}

	private final AttributeKey CONTEXT = new AttributeKey(getClass(), "context");

	public Context getContext(IoSession session) {
		Context ctx = (Context) session.getAttribute(CONTEXT);
		if (ctx == null) {
			ctx = new Context();
			session.setAttribute(CONTEXT, ctx);
		}
		return ctx;
	}

	class Context {
		private IoBuffer ioBuffer = IoBuffer.allocate(100).setAutoExpand(true);

		public IoBuffer getIoBuffer() {
			return ioBuffer;
		}
	}

	public static void setSecretKey(IoSession session, String key) {
		// TODO Auto-generated method stub

	}

	public static String getSecretKey(IoSession session) {
		// TODO Auto-generated method stub
		return null;
	}

	public static String toHexString(byte[] byteArray) {
		final StringBuilder hexString = new StringBuilder("");
		if (byteArray == null || byteArray.length <= 0)
			return null;
		for (int i = 0; i < byteArray.length; i++) {
			int v = byteArray[i] & 0xFF;
			String hv = Integer.toHexString(v);
			if (hv.length() < 2) {
				hexString.append(0);
			}
			hexString.append(hv);
		}
		return hexString.toString().toLowerCase();
	}
}
